<?php

namespace Piz;

class App
{
    //实例
    private static $instance;
    //映射表
    private static $map = [];

    //防止被一些讨厌的小伙伴不停的实例化，自己玩。
    private function __construct()
    {
    }

    //还得让伙伴能实例化，并且能用它。。
    public static function get_instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function websocket($server, $frame)
    {
        $router = $router = Router::get_instance()->websocket($frame->data);

        $app_namespace = Config::get_instance()->get('app.namespace');
        $module = $router['m'];
        $controller = $router['c'];
        $action = $router['a'];
        $param = $router['p'];

        $classname = "\\{$app_namespace}\\modules\\{$module}\\{$controller}";

        if (!isset(self::$map[$classname])) {
            try {
                $class = new $classname;
                //必须继承 Piz\WsController
                if (get_parent_class($class) != 'Piz\WsController') {
                    echo "[{$classname}]  必须继承 Piz\WsController", PHP_EOL;
                    return;
                }
                self::$map[$classname] = $class;
            } catch (\Exception $e) {
                Log::get_instance()->write('DEBUG', $e);
                echo $e->getMessage(), PHP_EOL;
                return;
            }
        }
        try {
            self::$map[$classname]->server = $server;
            self::$map[$classname]->fd = $frame->fd;
            self::$map[$classname]->param = $param;
            self::$map[$classname]->task = Task::get_instance()->set_server($server);
            self::$map[$classname]->$action();
            Log::get_instance()->write('DEBUG-classname', "ACTION");
        } catch (\Exception $e) {
            echo $e->getMessage(), PHP_EOL;
            return;
        }
    }

    public function http($server, $request, $response)
    {
        if ($request->server['request_uri'] == '/favicon.ico') return;
        $req = Request::get_instance();
        $req->set($request);
        $router = Router::get_instance()->http($req->server['request_uri']);

        $app_namespace = Config::get_instance()->get('app.namespace');
        $module = $router['m'];
        $controller = $router['c'];
        $action = $router['a'];
        $param = $router['p'];
        $classname = "\\{$app_namespace}\\modules\\{$module}\\{$controller}";

        if (!isset(self::$map[$classname])) {
            try {
                $class = new $classname;
                //必须继承 Piz\Controller
                if (get_parent_class($class) != 'Piz\Controller') {
                    $response->header('Content-type', "text/html;charset=utf-8;");
                    $response->status(503);
                    $response->end('503 Service Unavailable');
                    echo "[{$classname}]  必须继承 Piz\Controller", PHP_EOL;
                    return;
                }
                self::$map[$classname] = $class;
            } catch (\Exception $e) {
                $response->header('Content-type', "text/html;charset=utf-8;");
                $response->status(503);
                $response->end($e->getMessage());
                return;
            }
        }
        try {
            //测试效果
            if (!empty(ob_get_contents())) ob_end_clean();
            ob_start();
            self::$map[$classname]->$action($param);
            $content = ob_get_contents();
            ob_end_clean();
            $response->end($content);
        } catch (\Exception $e) {      //在此处返回 404错误的原因是因为加载器已经在查找不到文件时有说错误说明
            $response->header('Content-type', "text/html;charset=utf-8;");
            $response->status(404);
            $response->end('404 NOT FOUND');
            return;
        }
    }
}